/**
 * 
 */
package com.fox.webapp.web;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fox.webapp.domain.Account;
import com.fox.webapp.domain.Bank;
import com.fox.webapp.domain.Broker;
import com.fox.webapp.domain.CommissionRecord;
import com.fox.webapp.domain.Communicate;
import com.fox.webapp.domain.LoginLog;
import com.fox.webapp.domain.Person;
import com.fox.webapp.domain.SiteMessage;
import com.fox.webapp.domain.WithdrawRecord;
import com.fox.webapp.service.IAccountService;
import com.fox.webapp.service.IAsyncActionService;
import com.fox.webapp.service.IBrokerService;
import com.fox.webapp.service.ILoginLogService;
import com.fox.webapp.service.IPersonService;
import com.fox.webapp.utils.Constant;
import com.fox.webapp.utils.DataTablesRequest;
import com.fox.webapp.utils.DataTablesResponse;
import com.fox.webapp.utils.ErrorCoding;
import com.fox.webapp.utils.WebUtil;
import com.fox.webapp.utils.ZXingEncoder;
import com.springcryptoutils.core.digest.Digester;

/**
 * @author yockii
 *
 */
@Controller
@RequestMapping("i")
public class PersonController {

	private static final Logger logger = LoggerFactory.getLogger(PersonController.class);
	@Autowired
	private IPersonService personService;
	@Autowired
	private IAccountService accountService;
	@Autowired
	private ILoginLogService loginLogService;
	@Autowired
	private IAsyncActionService asyncActionService;
	@Autowired
	private Digester digester;
	
	@RequestMapping(value = {"", "index", "index.html"}, method = RequestMethod.GET)
	public String userCenter(Model model, HttpSession session){
		Person p = (Person)session.getAttribute(Constant.SESSION_USER);
		model.addAttribute("accountCount", accountService.getMyAccountCount(p));
		Page<LoginLog> llp = loginLogService.getMyLoginLog(p, 0, 5);
		model.addAttribute("loginLogList", llp.getContent());
		Page<CommissionRecord> crp = personService.findMyCommissionRecord(p, 0, 5);
		model.addAttribute("commissionRecordList", crp == null ? new ArrayList<CommissionRecord>(): crp.getContent());
		return "uc/main";
	}
	
	@RequestMapping(value = "references.html", method = RequestMethod.GET)
	public String referencePage(HttpSession session, Model model){
		return referencePage(0, session, model);
	}
	
	@RequestMapping(value = "references/{page}", method = RequestMethod.GET)
	public String referencePage(@PathVariable int page, HttpSession session, Model model){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		Page<Person> pPage = personService.getMyReferences(me, page, 10);
		model.addAttribute("pPage", pPage);
		return "uc/ref";
	}
	
	@RequestMapping(value = "loginLog.html", method = RequestMethod.GET)
	public String loginLogPage(HttpSession session, Model model){
		return loginLogPage(0, session, model);
	}
	
	@RequestMapping(value = "loginLog/{page}", method = RequestMethod.GET)
	public String loginLogPage(@PathVariable int page, HttpSession session, Model model){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		Page<LoginLog> llPage = loginLogService.getMyLoginLog(me, page, 10);
		model.addAttribute("llPage", llPage);
		return "uc/loginLog";
	}
	
	@RequestMapping(value = "commission.html", method = RequestMethod.GET)
	public String commissionPage(HttpSession session, Model model){
		return commissionPage(0, session, model);
	}
	
	@RequestMapping(value = "commission/{page}", method = RequestMethod.GET)
	public String commissionPage(@PathVariable int page, HttpSession session, Model model){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		Page<CommissionRecord> crPage = personService.findMyCommissionRecord(me, page, 10);
		model.addAttribute("crPage", crPage);
		return "uc/commission";
	}
	
	@RequestMapping(value = {"bank", "bank.html"}, method = RequestMethod.GET)
	public String bankPage(HttpSession session, Model model){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		Bank bank = me.getBank();
		model.addAttribute("bank", bank);
		return "uc/bank";
	}
	
	@RequestMapping(value = {"myInfo", "myInfo.html"}, method = RequestMethod.GET)
	public String myInfoView(){
		return "uc/myInfo";
	}
	
	@RequestMapping(value = {"myInfo"}, method = RequestMethod.POST)
	public String simpleInfoModify(Person person, HttpSession session, Model model){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		person.setId(me.getId());
		person.setPassword(digester.digest(person.getPassword()));
		Person p = personService.modifySimpleInfo(person);
		model.addAttribute("modifyResult", p != null);
		if(p != null){
			session.setAttribute(Constant.SESSION_USER, p);
		}
		return myInfoView();
	}
	
	@RequestMapping(value = {"p", "p.html"}, method = RequestMethod.GET)
	public String passwordAndSQAPage(){
		return "uc/p";
	}
	
	@RequestMapping(value = {"updatePassword"}, method = RequestMethod.POST)
	public String updatePassword(String oldPassword, String newPassword, String confirmPassword, HttpSession session, Model model){
		if (!StringUtils.hasText(oldPassword) || !StringUtils.hasText(newPassword) || !StringUtils.hasText(confirmPassword)) {
			model.addAttribute("modifyResult", false);
			return passwordAndSQAPage();
		}
		if (!newPassword.equals(confirmPassword)) {
			model.addAttribute("modifyResult", false);
			return passwordAndSQAPage();
		}
		Person p = (Person)session.getAttribute(Constant.SESSION_USER);
		oldPassword = digester.digest(oldPassword);
		if(!p.getPassword().equals(oldPassword)){
			model.addAttribute("modifyResult", false);
			return passwordAndSQAPage();
		}
		p.setPassword(digester.digest(newPassword));
		p = personService.modifyPassword(p);
		if(p != null){
			session.setAttribute(Constant.SESSION_USER, p);
			model.addAttribute("modifyResult", true);
		} else {
			model.addAttribute("modifyResult", false);
		}
		return passwordAndSQAPage();
	}
	
	@RequestMapping(value = "updateQA", method = RequestMethod.POST)
	public String updateQA(String question, String answer, String QAPassword, HttpSession session, Model model){
		if(!StringUtils.hasText(question) || !StringUtils.hasText(answer) || !StringUtils.hasText(QAPassword)){
			model.addAttribute("modifyResult", false);
			return passwordAndSQAPage();
		}
		Person p = (Person)session.getAttribute(Constant.SESSION_USER);
		if(!p.getPassword().equals(digester.digest(QAPassword))){
			model.addAttribute("modifyResult", false);
			return passwordAndSQAPage();
		}
		p.setSecurityQuestion(question);
		p.setSecurityAnswer(digester.digest(answer));
		p = personService.modifyQA(p);
		if(p != null){
			session.setAttribute(Constant.SESSION_USER, p);
			model.addAttribute("modifyResult", true);
		} else {
			model.addAttribute("modifyResult", false);
		}
		return passwordAndSQAPage();
	}
	
	@RequestMapping(value = {"bankInfo"}, method = RequestMethod.POST)
	public String bankInfoModify(Person person, Bank bank, HttpSession session, Model model){
		if (!StringUtils.hasText(bank.getBankName()) || !StringUtils.hasText(bank.getBankNo()) || !StringUtils.hasText(bank.getName())) {
			model.addAttribute("modifyResult", false);
			return bankPage(session, model);
		}
		Person p = (Person)session.getAttribute(Constant.SESSION_USER);
		if(personService.updatePersonBank(p, bank)){
			model.addAttribute("modifyResult", true);
			session.setAttribute(Constant.SESSION_USER, p);
		} else {
			model.addAttribute("modifyResult", false);
		}
		return bankPage(session, model);
	}
	
	@RequestMapping(value = {"withDraw", "withDraw.html"}, method = RequestMethod.GET)
	public String withDrawPage(){
		return "uc/withDraw";
	}
	
	@RequestMapping(value = "canWithDraw", method= RequestMethod.GET)
	@ResponseBody
	public double canIWithdraw(HttpSession session){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		return me.getTotalBalance() == null ? 0d : (me.getTotalBalance() - (me.getWithDrawing()==null?0:me.getWithDrawing()));
	}
	
	@RequestMapping(value = "withDraw", method = RequestMethod.POST)
	@ResponseBody
	public int doWithdraw(double withDraw, HttpSession session, HttpServletRequest request){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		if(me.getTotalBalance() == null || (me.getTotalBalance() - me.getWithDrawing()) < withDraw){
			return Constant.RESULT_FAILED;
		}
		return personService.withdraw(me, withDraw, WebUtil.getIpAddr(request))?Constant.RESULT_SUCCESS:Constant.RESULT_FAILED;
	}
	
	@RequestMapping(value = {"withDrawHis.html"}, method = RequestMethod.GET)
	public String withdrawHisPage(HttpSession session, Model model){
		return withdrawHistory(session, model, 0);
	}
	
	@RequestMapping(value = {"withDrawHis/{page}"}, method = RequestMethod.GET)
	public String withdrawHistory(HttpSession session, Model model, @PathVariable int page){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		Page<WithdrawRecord> wrPage = personService.getMyWithdrawRecords(me, page, 10);
		model.addAttribute("wrPage", wrPage);
		return "uc/withdrawHistory";
	}
	
	@RequestMapping(value = "message.html", method = RequestMethod.GET)
	public String siteMessagePage(HttpSession session, Model model){
		return siteMessagePage(session, model, "inbox", 0);
	}
	
	@RequestMapping(value = "message/{fromOrTo}/{page}", method = RequestMethod.GET)
	public String siteMessagePage(HttpSession session, Model model, @PathVariable String fromOrTo, @PathVariable int page){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		boolean isFrom = "inbox".equalsIgnoreCase(fromOrTo);
		Page<SiteMessage> smPage = personService.getMyMessages(me, isFrom, page, 10);
		model.addAttribute("smPage", smPage);
		model.addAttribute("isFrom", isFrom);
		return "uc/siteMessage";
	}
	
	@RequestMapping(value = "sendMessage", method = RequestMethod.POST)
	@ResponseBody
	public int sendNewSiteMessage(SiteMessage sm, HttpSession session){
		int result = -1;
		String toUsername = sm.getToUsername();
		Person toPerson = personService.getPersonByUsername(toUsername);
		if(toPerson == null){
			return -3;
		}
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		sm.setFromUsername(me.getUsername());
		sm.setToUsername(toPerson.getUsername());
		sm.setIsSystem(false);
		sm.setSendTime(new Date());
		SiteMessage siteMessage = personService.sendSiteMessage(sm);
		if(siteMessage != null){
			result = 1;
		}
		return result;
	}
	
	@RequestMapping(value = {"communicate", "communicate.html"}, method = RequestMethod.GET)
	public String communicatePage(){
		return "uc/communicate";
	}
	
	@RequestMapping(value = {"communicate", "communicate.html"}, method = RequestMethod.POST)
	public String newCommunicate(HttpSession session, Model model, Communicate communicate){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		communicate.setApplier(me);
		communicate.setApplyTime(new Date());
		communicate.setReplied(false);
		boolean b = personService.addNewCommunicate(communicate);
		model.addAttribute(Constant.RESULT_STR, b?Constant.RESULT_SUCCESS:Constant.RESULT_FAILED);
		model.addAttribute("communicate", b?null:communicate);
		return communicatePage();
	}
	
	@RequestMapping(value = {"verifyEmail", "verifyEmail.html"}, method = RequestMethod.GET)
	public String verifyEmailPage(HttpSession session){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		asyncActionService.sendVerifyEmail(me);
		return "uc/verifyEmail";
	}
	
	@RequestMapping(value = {"verifyMobile", "verifyMobile.html"}, method = RequestMethod.GET)
	public String verifyMobilePage(HttpSession session){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		//TODO 手机验证
		return "uc/verifyMobile";
	}
	
	@RequestMapping(value = {"modifyVerifiedEmail", "modifyVerifiedEmail.html"}, method = RequestMethod.GET)
	public String modifyVerifiedEmail(Model model, HttpSession session){
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		if(personService.modifyVerifiedEmail(me)){
			model.addAttribute("person", me);
		}
		return "uc/modifyVerifiedEmail";
	}
	
	@RequestMapping(value = {"MyQrRefImg.png"}, method = RequestMethod.GET)
	public void qrcodePage(HttpSession session, HttpServletResponse response) throws IOException{
		Person me = (Person)session.getAttribute(Constant.SESSION_USER);
		
		personService.getMyQrcodeToStream(me, response.getOutputStream());
		
		response.getOutputStream().flush();
		response.getOutputStream().close();
	}
	
}
